home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1993-04-01 | 11.4 KB | 272 lines | [ TEXT/GEOL]
Instance Variables for HyperCard by Ted Kaehler, Apple Computer, Kaehler2@AppleLink.Apple.com Allows you to have variables attached to a button, shared field, or other HyperCard object. Each variable can have any value that any variable in a script can have. Names of variables may contain spaces, commas, or other special characters (enclose the variable name in double-quotes in your script). Instance variables are useful for storing more data with a button or field. A puzzle piece button wants to carry its home location with it. A phone dialing button needs a place to put the local area code, without it being a constant in the middle of its script. A background may need to carry some data useful to its scripts. An object may have any number of variables. Values are preserved when you quit. They stay with your stack when you drag it to another disk. The objects that can have variables are: a card button, a card field, the card itself, a bkgnd button, a shared field, or the background itself. Instance variables for background fields are not supported! This is because a background field is partly shared and partly local to the card. When you have the urge to put a variable into a background field, attach it instead to the either the card or the current background. How to call: Call allowInstVars once in each new background to initialize instance variables. It creates two background fields to keep the values in. To store into a variable, say putVar cdBk, myID, variable, value, cardID For example, to store “East” into the variable “Direction” in the button “Engine”, say putVar "cd", the id of card btn “Engine”, "Direction", “East” Use the function getVar to retrieve the value of a variable: getVar (cdBk, myID, variable, cardID) In this case is looks like: put getVar("cd",the id of card btn “Engine”, "Direction") into dir The last argument, cardID is optional. Leaving it out, as we did above, means the button on the current card. See the script for more detail on the arguments. The Fine Print The total size of all names and values or a single card cannot exceed 32K bytes. The characters { and } may not appear in any value or variable name name. Use with HyperCard 2.1 or later. The Script This belongs in the stack script of your stack. (Just putting it in the Home script is not the best. If you give your stack to someone, instance variables will stop working.) -- Allow Instance Variables for buttons, fields, cards, and backgrounds. -- (c) 1991 copyright Apple Computer, all rights reserved. -- Version 1.0 for HyperCard 2.1 -- This belongs in the stack script of your stack. -- (Just putting it in the Home script is not the best. If you then give -- your stack to someone, instance variables will stop working.) -- You call these: putVar, getVar, allowInstVars -- Bonus handlers: removeVar, hasThisVar, allVarsOf -- Internal use only: instVar, createBkgndFld on putVar cdBk,myID,variable,value,cardID -- Store the value of this variable in this object -- Example: putVar cd,the id of me,fred,45 -- a missing cardID means on the current card -- cdBk is cd or bk -- (where is this object? cd is card, bk is background) -- myID is: the short id of me -- variable is the name under which you want to store this value -- value is what you want to store -- value may not contain { or } characters -- cardID (optional) the id of the card that contains the object put instVar(cdBk,myID,variable,value,cardID) into dummy end putVar function getVar cdBk,myID,variable,cardID -- Retrieve the value of this variable in this object -- Example: getVar cd,the id of me,fred -- a missing cardID means on the current card -- cdBk is cd or bk -- (where is this object? cd is card, bk is background) -- myID is: the short id of me -- variable is the name under which you want to store this value. -- variable may not contain { or } characters -- it may contain spaces or other characters -- cardID (optional) the id of the card that contains the object return instVar(cdBk,myID,variable,"{}",cardID) --retrieval end getVar function instVar cdBk,myID,variable,value,cardID -- Get or put the value of a variable that belongs to a -- card button, card field, the card itself, a bkgnd button, -- shared field, or the bkgnd itself. -- User should not call this. Called from getVar, putVar and removeVar. -- Instance variables for bkgnd fields are not supported! This is -- because it a background field is part shared and part local to -- the card. Attach the variable to the card or to a shared -- field instead. -- Works for both storing and retireving, for both objects on a -- card and object shared across a background. -- If value is "{}" then we are retrieving a value from the -- dictionary. -- Note that myID is not enough information to actually find the -- button or field (we don't know which it is). But we don't -- care. We don't have to get at the button or field itself, -- just find it's variables in the dictionary! -- The search keys put "{" & variable & "{" & myID & "{" into startKey --{Fred{21{ put "}" & variable & "}" & myID & "}" into endKey --}Fred}21} if cardID is empty then put the short id of this card into holder -- on current card else put cardID into holder --on a specific card if cdBk = "bk" then put "call allowInstVars first" into theFld --background objects else put "you must call allowInstVars" into theFld --card specific -- The names of these fields are funny so that the user will know -- what to do when he gets and error because the fields are not there. -- If the field is missing, you must call allowInstVars (just once in -- each background) to initialize some hidden fields. put offset(startKey,bkgnd fld theFld of cd id holder) ¬ into startLoc --loc of {Fred{21{ if startLoc is 0 then --the key wasn't found if (cdBk is not "cd") and (cdBk is not "bk") then answer "First arg of putVar must be bk or cd" with "OK" if value = "{}" then --getting and it was not found put cdBK && "id" && myID && variable && "on card id" && holder answer "You must putVar into a variable" & return &¬ "before using getVar to read it." return "no value in:" && variable else --putting a value, create a new variable put return & startKey & value & endKey after bkgnd fld ¬ theFld of cd id holder return value end if end if put offset(endKey,bkgnd fld theFld of cd id holder) ¬ into endLoc --loc of }Fred}21} add length(startKey) to startLoc --loc after key, start of value subtract 1 from endLoc if value = "{}" then --getting a value -- Retrieve the value of the variable return char startLoc to endLoc of bkgnd fld theFld of cd id holder else if value = "re{}move" then --remove the variable to save space subtract length(startKey) from startLoc --loc before key add length(startKey) to endLoc --loc after end key put empty into char startLoc to endLoc of bkgnd fld ¬ theFld of cd id holder -- remove keys and value else -- Store the value in the dictionary over old value put value into char startLoc to endLoc of bkgnd fld ¬ theFld of cd id holder end if return value end if end instVar on allowInstVars -- Create a field for the instance variable dictionary. -- It has a funny name so the user will know what to do -- when he gets and error because the field is not there. createBkgndFld "you must call allowInstVars" --card variables createBkgndFld "call allowInstVars first" --bkgnd variables set sharedText of bkgnd fld "call allowInstVars first" to true set loc of bkgnd fld "call allowInstVars first" to 160,250 end allowInstVars on createBkgndFld theName -- Create hidden background field if not there already. -- Use this field for storing the dictionary of names and values. repeat with ii = 1 to the number of bkgnd fields put the short name of bkgnd field ii into myName if myName is theName then put "already there!" exit createBkgndFld --already exists end if end repeat -- Create a background field for the instance variable dictionary. doMenu "background" doMenu "New Field" put the number of bkgnd fields into num set the name of field num to theName hide field theName -- important! choose browse tool doMenu "Background" --get out of Background mode put "new is " & num --debugging end createBkgndFld -- Bonus handlers: removeVar, hasThisVar, allVarsOf on removeVar cdBk,myID,variable,cardID -- Remove this variable in this object -- Is not necessary. Only do it to save space when destroying -- a button or other object. -- Example: removeVar cd,the id of me,fred -- a missing cardID means on the current card -- see getVar for the meaning of the arguments put instVar(cdBk,myID,variable,"re{}move",cardID) into data -- this specal value means remove the variable from the dictionary end removeVar function hasThisVar cdBk,myID,variable,cardID -- Return true if this object has a variable of this name -- So a script can ask if the object has one before trying to read it. -- Example: hasThisVar(cd,the id of me,"fred") -- a missing cardID means on the current card -- cdBk is cd or bk -- (where is this object? cd is card, bk is background) -- myID is: the short id of me -- variable is the name under which you want to store this value -- cardID (optional) the id of the card that contains the object put "{" & variable & "{" & myID & "{" into startKey --{Fred{21{ if cardID is empty then put the short id of this card into holder -- on current card else put cardID into holder --on a specific card if cdBk = "bk" then put "call allowInstVars first" into theFld --background objects else put "you must call allowInstVars" into theFld --card specific return offset(startKey,bkgnd fld theFld of cd id holder) is not 0 end hasThisVar function allVarsOf cdBk,myID,cardID -- Return a list of the names of the variables in this object now. -- Returns a list of items separated by commas -- Example: allVarsOf(cd,the id of me) -- a missing cardID means on the current card -- cdBk is cd or bk -- (where is this object? cd is card, bk is background) -- myID is: the short id of me -- cardID (optional) the id of the card that contains the object put "{" & myID & "{" into startKey --{21{ if cardID is empty then put the short id of this card into holder -- on current card else put cardID into holder --on a specific card if cdBk = "bk" then put "call allowInstVars first" into theFld --background objects else put "you must call allowInstVars" into theFld --card specific put bkgnd fld theFld of cd id holder into rawData put empty into list repeat put offset(startKey,rawData) into index --{21{ if index = 0 then return list put index-1 into ii repeat until ii = 1 -- will not leave this way if char ii of rawData = "{" then if list is not empty then put "," after list put (char ii+1 to index-1 of rawData) after list --fred delete char 1 to index+5 of rawData -- remove start of this -- variable so the next one will be the first one found else subtract 1 from ii --backup one char end if end repeat end repeat end allVarsOf